package br.com.sovi.gwt.client.rastreamento;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import br.com.sovi.gwt.client.component.mainmenu.MainMenuOptionsEnum;
import br.com.sovi.gwt.client.entity.Ponto;
import br.com.sovi.gwt.client.entity.rastreamento.Rastreavel;
import br.com.sovi.gwt.client.rastreamento.service.RastreamentoService;
import br.com.sovi.gwt.client.rastreamento.service.RastreamentoServiceAsync;
import br.com.sovi.gwt.client.rpc.SecureAsyncCallback;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Timer;

public class RastreamentoTimerController {

	private static RastreamentoTimerController instance;

	public static RastreamentoTimerController get() {
		if (instance == null) {
			instance = new RastreamentoTimerController();
		}
		return instance;
	}

	public static int UPDATE_INTERVAL = 30000;

	private RastreamentoServiceAsync service;

	private Map<Rastreavel, Timer> timers = new HashMap<Rastreavel, Timer>();

	public RastreamentoTimerController() {
		History.addValueChangeHandler(new ValueChangeHandler<String>() {
			@Override
			public void onValueChange(ValueChangeEvent<String> event) {
				if (!event.getValue().equals(MainMenuOptionsEnum.RASTREAMENTO.getToken())) {
					Collection<Timer> values = timers.values();

					for (Timer timer : values) {
						timer.cancel();
					}
				}
			}
		});
		service = (RastreamentoServiceAsync) GWT.create(RastreamentoService.class);
	}

	public RastreamentoServiceAsync getService() {
		return service;
	}

	public Timer addTimer(final Rastreavel rastreavel, final Marker marker, final MapWidget map) {
		Timer rastreadorTimer = new Timer() {
			@Override
			public void run() {
				GWT.log("Rodando timer: " + rastreavel.getSerial(), null);
				
				RastreamentoTimerController.this.getService().getUltimoPonto(rastreavel,
						new SecureAsyncCallback<Ponto>() {

							@Override
							public void onSuccess(Ponto result) {
								LatLng lng = LatLng.newInstance(result.getLatitude(), result.getLongitude());
								marker.setLatLng(lng);
								map.panTo(lng);
							}

							@Override
							public void onFailure(Throwable caught) {
								super.onFailure(caught);
								GWT.log(".onFailure() ", caught);
							}

						});
			}
		};

		timers.put(rastreavel, rastreadorTimer);

		return rastreadorTimer;
	}

	public Timer startRastreamento(Rastreavel rastreavel) {
		Timer timer = timers.get(rastreavel);

		if (timer != null) {
			timer.scheduleRepeating(UPDATE_INTERVAL);
			return timer;
		}
		else {
			return null;
		}
	}

	public Timer stopRastreamento(Rastreavel rastreavel) {
		Timer timer = timers.get(rastreavel);

		if (timer != null) {
			timer.cancel();
			return timer;
		}
		else {
			return null;
		}
	}

}
